package rpcserver

import (
	"fmt"
	"gitee.com/jamon/espoir_go/common"
	"gitee.com/jamon/espoir_go/global"
	"gitee.com/jamon/espoir_go/logger"
	"net"
	"net/rpc"
	"sync"
)

type Manager struct {
	quitOnce sync.Once

	server *net.Listener
}

func NewManager() (mgr *Manager, err error) {
	mgr = &Manager{}
	return
}

func (mgr *Manager) InitRpcServer() (err error) {
	conf := global.GetNodeData().Config.RPC
	addr := fmt.Sprintf(":%v", conf.Port)
	server, err := net.Listen("tcp", addr)
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})
		return
	}
	mgr.server = &server
	handler, err := NewRequestHandler()
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})
		return err
	}
	err = rpc.Register(handler)
	if err != nil {
		return err
	}

	// 注册推送消息处理
	pushHandler, err := NewPushHandler()
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})
		return
	}
	err = rpc.Register(pushHandler)
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})

	}

	// 注册内部通知处理
	internalNotifyHandler, err := NewInternalHandler()
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})
		return
	}
	err = rpc.Register(internalNotifyHandler)
	if err != nil {
		logger.Error("initRpcServer: ", logger.Kwargs{"err": err})
		return
	}
	return
}

func (mgr *Manager) Run() {
	mgr.Listen()
}

func (mgr *Manager) Listen() {
	for {
		conn, err := (*mgr.server).Accept()
		if err != nil {
			logger.Error("Listen: ", logger.Kwargs{"err": err})
			continue
		}
		go common.SafeRun(func() {
			rpc.ServeConn(conn)
		})
	}
}

func (mgr *Manager) Close() {
	mgr.quitOnce.Do(func() {
		err := (*mgr.server).Close()
		if err != nil {
			return
		}
	})
}
